// Protocol3 智能协议解析器
// 提供基于协议绑定的智能协议解析、缓存和回退机制

import type {
  MerchantChannelConfig3,
  QRCodeConfig,
  ProtocolBinding,
  Protocol3ResolveResult,
  ChannelConfigType
} from '../types/protocol3-types'
import {
  ProtocolBindingStatus,
  generateProtocolId,
  formatTimestamp,
  deepClone
} from '../types/protocol3-types'
import { protocol3Manager } from './protocol3-manager'

// 解析请求接口
export interface ResolveRequest {
  channelCode: string
  configType: string
  requestId?: string
}

// 批量解析结果
export interface BatchResolveResult {
  results: Protocol3ResolveResult[]
  totalRequests: number
  successCount: number
  failureCount: number
  totalTime: number
  averageTime: number
}

// 解析缓存条目
interface ResolveCache {
  result: Protocol3ResolveResult
  timestamp: number
  hitCount: number
}

// Protocol3 智能解析器
export class Protocol3Resolver {
  private static instance: Protocol3Resolver
  private cache = new Map<string, ResolveCache>()
  private maxCacheSize = 200
  private cacheTimeout = 5 * 60 * 1000 // 5分钟缓存超时
  
  private constructor() {
    // 私有构造函数，确保单例
  }
  
  public static getInstance(): Protocol3Resolver {
    if (!Protocol3Resolver.instance) {
      Protocol3Resolver.instance = new Protocol3Resolver()
    }
    return Protocol3Resolver.instance
  }
  
  /**
   * 解析协议 - 核心解析方法
   */
  public resolveProtocol(channelCode: string, configType: string): Protocol3ResolveResult {
    const startTime = Date.now()
    const cacheKey = `${channelCode}:${configType}`
    
    try {
      // 1. 尝试从缓存获取
      const cached = this.getFromCache(cacheKey)
      if (cached) {
        return {
          ...cached,
          cacheHit: true,
          resolveTime: Date.now() - startTime
        }
      }
      
      // 2. 查找激活的协议绑定
      const bindings = this.findActiveBindings(channelCode, configType)
      
      if (bindings.length > 0) {
        // 使用优先级最高的绑定
        const primaryBinding = bindings[0]
        const protocol = protocol3Manager.getProtocol(primaryBinding.protocolId)
        
        if (protocol) {
          const result = this.createResolveResult(protocol, bindings, 'binding', false, Date.now() - startTime)
          this.setCache(cacheKey, result)
          return result
        }
      }
      
      // 3. 生成默认协议（如果没有找到绑定）
      const defaultProtocol = this.generateDefaultProtocol(channelCode, configType)
      const result = this.createResolveResult(defaultProtocol, [], 'registry', true, Date.now() - startTime)
      this.setCache(cacheKey, result)
      return result
      
    } catch (error) {
      // 发生错误时返回默认协议
      const defaultProtocol = this.generateDefaultProtocol(channelCode, configType)
      return this.createResolveResult(defaultProtocol, [], 'registry', true, Date.now() - startTime)
    }
  }
  
  /**
   * 带回退的协议解析
   */
  public resolveWithFallback(channelCode: string, configType: string = 'MERCHANT_CONFIG'): Protocol3ResolveResult {
    return this.resolveProtocol(channelCode, configType)
  }
  
  /**
   * 批量解析协议
   */
  public resolveBatch(requests: ResolveRequest[]): BatchResolveResult {
    const startTime = Date.now()
    const results: Protocol3ResolveResult[] = []
    let successCount = 0
    let failureCount = 0
    
    for (const request of requests) {
      try {
        const result = this.resolveProtocol(request.channelCode, request.configType)
        results.push(result)
        successCount++
      } catch (error) {
        // 即使发生错误，也会返回默认协议，所以这里主要是记录
        const fallbackResult = this.resolveProtocol(request.channelCode, request.configType)
        results.push(fallbackResult)
        failureCount++
      }
    }
    
    const totalTime = Date.now() - startTime
    
    return {
      results,
      totalRequests: requests.length,
      successCount,
      failureCount,
      totalTime,
      averageTime: requests.length > 0 ? totalTime / requests.length : 0
    }
  }
  
  /**
   * 预热缓存 - 为常用的渠道/配置类型组合预加载
   */
  public warmupCache(channelCodes: string[], configTypes: string[] = ['MERCHANT_CONFIG', 'QR_CODE_CONFIG']): void {
    const requests: ResolveRequest[] = []
    
    for (const channelCode of channelCodes) {
      for (const configType of configTypes) {
        requests.push({ channelCode, configType })
      }
    }
    
    this.resolveBatch(requests)
  }
  
  /**
   * 检查协议绑定是否存在
   */
  public hasProtocolBinding(channelCode: string, configType: string): boolean {
    const bindings = this.findActiveBindings(channelCode, configType)
    return bindings.length > 0
  }
  
  /**
   * 获取支持的渠道列表
   */
  public getSupportedChannels(): string[] {
    const channelConfigTypes = protocol3Manager.getChannelConfigTypes()
    const channels = new Set<string>()
    
    for (const config of channelConfigTypes) {
      channels.add(config.channelCode)
    }
    
    return Array.from(channels)
  }
  
  /**
   * 获取渠道支持的配置类型
   */
  public getSupportedConfigTypes(channelCode: string): string[] {
    const channelConfigTypes = protocol3Manager.getChannelConfigTypes(channelCode)
    return channelConfigTypes.map(config => config.configType)
  }
  
  /**
   * 清除解析缓存
   */
  public clearCache(): void {
    this.cache.clear()
  }
  
  /**
   * 获取缓存统计信息
   */
  public getCacheStats(): {
    size: number
    hitRate: number
    totalHits: number
    totalMisses: number
    keys: string[]
  } {
    let totalHits = 0
    let totalMisses = 0
    
    for (const entry of this.cache.values()) {
      totalHits += entry.hitCount
    }
    
    // 这里简化处理，实际的miss统计需要在resolve过程中记录
    const total = totalHits + totalMisses
    
    return {
      size: this.cache.size,
      hitRate: total > 0 ? totalHits / total : 0,
      totalHits,
      totalMisses,
      keys: Array.from(this.cache.keys())
    }
  }
  
  /**
   * 清理过期缓存
   */
  public cleanupExpiredCache(): number {
    const now = Date.now()
    let cleanedCount = 0
    
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > this.cacheTimeout) {
        this.cache.delete(key)
        cleanedCount++
      }
    }
    
    return cleanedCount
  }
  
  /**
   * 获取协议绑定信息
   */
  public getProtocolBindings(channelCode: string, configType: string): ProtocolBinding[] {
    return protocol3Manager.getChannelConfigBindings(channelCode, configType)
  }
  
  /**
   * 获取协议绑定统计信息
   */
  public getBindingStatistics(): {
    totalBindings: number
    activeBindings: number
    inactiveBindings: number
    pendingBindings: number
    bindingsByChannel: Record<string, number>
    bindingsByConfigType: Record<string, number>
  } {
    const allBindings = protocol3Manager.getAllProtocolBindings()
    const bindingsByChannel: Record<string, number> = {}
    const bindingsByConfigType: Record<string, number> = {}
    
    let activeBindings = 0
    let inactiveBindings = 0
    let pendingBindings = 0
    
    for (const binding of allBindings) {
      // 按状态统计
      switch (binding.status) {
        case ProtocolBindingStatus.ACTIVE:
          activeBindings++
          break
        case ProtocolBindingStatus.INACTIVE:
          inactiveBindings++
          break
        case ProtocolBindingStatus.PENDING:
          pendingBindings++
          break
      }
      
      // 按渠道统计
      bindingsByChannel[binding.channelCode] = (bindingsByChannel[binding.channelCode] || 0) + 1
      
      // 按配置类型统计
      bindingsByConfigType[binding.configType] = (bindingsByConfigType[binding.configType] || 0) + 1
    }
    
    return {
      totalBindings: allBindings.length,
      activeBindings,
      inactiveBindings,
      pendingBindings,
      bindingsByChannel,
      bindingsByConfigType
    }
  }
  
  // ==================== 私有方法 ====================
  
  /**
   * 查找激活的协议绑定
   */
  private findActiveBindings(channelCode: string, configType: string): ProtocolBinding[] {
    const bindings = protocol3Manager.getChannelConfigBindings(channelCode, configType)
    return bindings
      .filter(binding => binding.status === ProtocolBindingStatus.ACTIVE)
      .sort((a, b) => a.priority - b.priority) // 按优先级排序
  }
  
  /**
   * 生成默认协议
   */
  private generateDefaultProtocol(channelCode: string, configType: string): MerchantChannelConfig3 {
    const protocolId = generateProtocolId(`PROTOCOL3_${channelCode}_${configType}`)
    
    // 生成基本的默认配置段
    const defaultConfigSections = [
      {
        sectionKey: 'basic',
        sectionName: '基础配置',
        description: '基础配置信息',
        icon: 'SettingOutlined',
        order: 1,
        collapsed: false,
        fields: [
          {
            fieldKey: 'appId',
            fieldName: '应用ID',
            fieldType: 'INPUT' as any,
            required: true,
            defaultValue: '',
            placeholder: '请输入应用ID',
            description: '应用标识符'
          },
          {
            fieldKey: 'appSecret',
            fieldName: '应用密钥',
            fieldType: 'PASSWORD' as any,
            required: true,
            defaultValue: '',
            placeholder: '请输入应用密钥',
            description: '应用密钥'
          }
        ],
        defaultValues: {
          appId: '',
          appSecret: ''
        }
      }
    ]
    
    // 创建默认协议配置
    const defaultProtocol: MerchantChannelConfig3 = {
      protocolId,
      protocolType: 'MERCHANT_CHANNEL_CONFIG_V3' as any,
      name: `${channelCode} - ${configType} (默认协议)`,
      version: '3.0.0-default',
      description: `${channelCode}渠道${configType}配置类型的默认协议`,
      enabled: true,
      
      // 使用默认的配置段
      configSections: defaultConfigSections,
      
      // 默认UI配置
      uiConfig: {
        layout: 'horizontal',
        labelWidth: 120,
        showDescription: true,
        grouping: 'sections'
      },
      
      metadata: {
        author: 'Protocol3 Auto Generator',
        createTime: formatTimestamp(Date.now()),
        updateTime: formatTimestamp(Date.now()),
        tags: [channelCode, configType, 'default-protocol'],
        category: '默认协议',
        documentation: '此协议由Protocol3系统自动生成的默认协议'
      }
    }
    
    return defaultProtocol
  }
  
  /**
   * 创建解析结果
   */
  private createResolveResult(
    protocol: MerchantChannelConfig3 | QRCodeConfig,
    bindings: ProtocolBinding[],
    source: 'registry' | 'binding',
    isDefault: boolean,
    resolveTime: number
  ): Protocol3ResolveResult {
    return {
      protocol: deepClone(protocol) as MerchantChannelConfig3, // 简化处理，实际应该判断协议类型
      protocolId: protocol.protocolId,
      bindings: deepClone(bindings),
      isDefault,
      source,
      cacheHit: false,
      resolveTime
    }
  }
  
  /**
   * 从缓存获取结果
   */
  private getFromCache(cacheKey: string): Protocol3ResolveResult | null {
    const entry = this.cache.get(cacheKey)
    if (!entry) {
      return null
    }
    
    // 检查缓存是否过期
    if (Date.now() - entry.timestamp > this.cacheTimeout) {
      this.cache.delete(cacheKey)
      return null
    }
    
    // 增加命中计数
    entry.hitCount++
    
    return deepClone(entry.result)
  }
  
  /**
   * 设置缓存
   */
  private setCache(cacheKey: string, result: Protocol3ResolveResult): void {
    // LRU缓存清理
    if (this.cache.size >= this.maxCacheSize) {
      const oldestKey = this.cache.keys().next().value
      this.cache.delete(oldestKey)
    }
    
    this.cache.set(cacheKey, {
      result: deepClone(result),
      timestamp: Date.now(),
      hitCount: 0
    })
  }
}

// 导出单例实例
export const protocol3Resolver = Protocol3Resolver.getInstance()

// 便捷函数
export function resolveProtocol3(channelCode: string, configType: string): Protocol3ResolveResult {
  return protocol3Resolver.resolveProtocol(channelCode, configType)
}

export function resolveProtocol3WithFallback(channelCode: string, configType?: string): Protocol3ResolveResult {
  return protocol3Resolver.resolveWithFallback(channelCode, configType)
}

export function resolveProtocol3Batch(requests: ResolveRequest[]): BatchResolveResult {
  return protocol3Resolver.resolveBatch(requests)
}

export function hasProtocol3Binding(channelCode: string, configType: string): boolean {
  return protocol3Resolver.hasProtocolBinding(channelCode, configType)
}

export function getProtocol3SupportedChannels(): string[] {
  return protocol3Resolver.getSupportedChannels()
}

export function getProtocol3SupportedConfigTypes(channelCode: string): string[] {
  return protocol3Resolver.getSupportedConfigTypes(channelCode)
}

export function warmupProtocol3Cache(channelCodes: string[], configTypes?: string[]): void {
  protocol3Resolver.warmupCache(channelCodes, configTypes)
}

export function getProtocol3Bindings(channelCode: string, configType: string): ProtocolBinding[] {
  return protocol3Resolver.getProtocolBindings(channelCode, configType)
}

export function getProtocol3BindingStatistics(): any {
  return protocol3Resolver.getBindingStatistics()
}

// 默认导出
export default {
  Protocol3Resolver,
  protocol3Resolver,
  resolveProtocol3,
  resolveProtocol3WithFallback,
  resolveProtocol3Batch,
  hasProtocol3Binding,
  getProtocol3SupportedChannels,
  getProtocol3SupportedConfigTypes,
  warmupProtocol3Cache,
  getProtocol3Bindings,
  getProtocol3BindingStatistics
}